package me.ahoukuse.capturedemov1;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.annotation.SuppressLint;
import android.content.Intent;
import android.graphics.ImageFormat;
import android.graphics.SurfaceTexture;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CameraMetadata;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.media.Image;
import android.media.ImageReader;
import android.os.Bundle;
import android.util.Log;
import android.util.Size;
import android.view.Surface;
import android.view.TextureView;

import java.nio.ByteBuffer;
import java.util.Arrays;

public class CameraPreview extends AppCompatActivity {

    private String expectCameraId;
    private Size expectSize;                    // 期望录制的视频分辨率，选取相机设备支持的第一个分辨率
    private CameraDevice camera;                // 使用的相机设备
    private ImageReader imageReader;
    private CaptureRequest.Builder previewRequestBuilder;
    private CameraCaptureSession captureSession;
    private TextureView textureView;            //预览界面
    private NetworkThread networkThread;
    private int image_height;
    private int image_width;
    private int jump = 2;
    private int idx = 0;
    private String server_ip;
    private int fragmentSize;
    //传输模式：0代表tcp, 1代表udp
    private int transMode = 0;

    private CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {
        @Override
        public void onOpened(@NonNull CameraDevice cameraDevice) {
            camera = cameraDevice;
            Log.d("Test", "onOpened: 相机打开");
            try {
                // 执行相机打开后的配置
                startPreview();
            } catch (CameraAccessException e) {
                e.printStackTrace();
            }

        }

        @Override
        public void onDisconnected(@NonNull CameraDevice cameraDevice) {
            Log.d("Debug", "onDisconnected: 相机关闭");
        }

        @Override
        public void onError(@NonNull CameraDevice cameraDevice, int i) {
            Log.d("Debug", "onError: 相机打开失败");
            cameraDevice.close();
        }
    };


    @SuppressLint("MissingPermission")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_camera_preview);
        Intent intent = getIntent();
        image_height = intent.getIntExtra("image_height",600);
        image_width = intent.getIntExtra("image_width",300);
        server_ip = intent.getStringExtra("server_ip");
        transMode = intent.getIntExtra("trans_mode", 0);
        fragmentSize = intent.getIntExtra("fragment_size", 32);
        Log.d("Debug", String.format("server ip: %s", server_ip));
        if ("".equals(server_ip)) {
            server_ip = "192.168.1.111";
        }
        CameraManager cameraManager = (CameraManager) getSystemService(CAMERA_SERVICE);
        textureView = (TextureView) findViewById(R.id.camera_view);
        if (networkThread == null) {
            if (transMode == 0)
                networkThread = new NetworkThreadTCP(server_ip);
            else if (transMode == 1) {
                networkThread = new NetworkThreadUDP(server_ip, fragmentSize);
            }
            assert networkThread != null;
            networkThread.start();
        }
        String[] cameraIds = null;
        try {
            cameraIds = cameraManager.getCameraIdList();
            for (String id : cameraIds) {
                CameraCharacteristics cameraCharacteristics =
                        cameraManager.getCameraCharacteristics(id);
                Integer facing = cameraCharacteristics.get(CameraCharacteristics.LENS_FACING);
                assert facing != null;
                // 将后置相机设为目标相机
                if (facing == CameraMetadata.LENS_FACING_BACK) {
                    expectCameraId = id;
                    StreamConfigurationMap map = cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
                    assert map != null;
                    //选取目标相机支持的第一个分辨率为目标分辨率
                    expectSize = map.getOutputSizes(ImageFormat.JPEG)[0];
                    Log.d("Debug", String.format("Current Image Size: %dpx*%dpx",expectSize.getWidth(),expectSize.getHeight()));
                }
            }
            cameraManager.openCamera(expectCameraId, stateCallback, null);
        } catch (CameraAccessException e) {
            Log.d("Debug", "打开相机失败, 权限错误");
        }
    }

    @Override
    protected void onStop() {
        super.onStop();
        if (camera != null) {
            captureSession.close();
            camera.close();
        }
        networkThread.setExit(true);
        networkThread.addData(new byte[0]);
    }

    private void startPreview() throws CameraAccessException {
        imageReader = ImageReader.newInstance(image_width, image_height, ImageFormat.JPEG, 2);
        imageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
            @Override
            public void onImageAvailable(ImageReader imageReader) {
                // 相机获取的图片数据在这里处理
                Image image = imageReader.acquireLatestImage();
                if (image == null) {
                    return;
                }
                /* if (idx % jump != 0) {
                    idx = (idx+1)%jump;
                    image.close();
                    return;
                }
                idx = (idx+1)%jump;*/

                Image.Plane plane = image.getPlanes()[0];
                ByteBuffer byteBuffer = plane.getBuffer();
                byte[] imageBytes = new byte[byteBuffer.capacity()];
                byteBuffer.get(imageBytes);
                networkThread.addData(imageBytes);
                image.close();

            }
        }, null);
        SurfaceTexture surfaceTexture = textureView.getSurfaceTexture();
        assert surfaceTexture != null;
        surfaceTexture.setDefaultBufferSize(expectSize.getWidth(), expectSize.getHeight());
        Surface surface = new Surface(surfaceTexture);

        previewRequestBuilder = camera.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
        previewRequestBuilder.addTarget(surface);
        previewRequestBuilder.addTarget(imageReader.getSurface());
        camera.createCaptureSession(Arrays.asList(surface, imageReader.getSurface()), new CameraCaptureSession.StateCallback() {
            @Override
            public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {
                Log.d("Test", "onConfigured:配置成功 ");
                captureSession = cameraCaptureSession;
                try {
                    cameraCaptureSession.setRepeatingRequest(previewRequestBuilder.build(),null,null);
                } catch (CameraAccessException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {

            }
        },null);
    }
}
